﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#include "ElementId.h"
#include "GcmpDatabase.h"
#include "WeakReferenceable.h"

namespace gcmp
{
    class IIOStream;
    class IDocument;
    class UniIdentity;

    /// \brief 对象保存信息接口
    class GCMP_DATABASE_EXPORT IObjectIOInfo
    {
        DEFINE_CAST_BASE(gcmp::IObjectIOInfo)
    public:
        /// \brief 析构函数
        ///
        /// \return 无
        virtual ~IObjectIOInfo() = 0;

        /// \brief  获取对象Id
        /// \return 对象的Id
        virtual const ElementId& GetObjectId() const = 0;
    };

    /// \brief 文件保存信息接口
    class GCMP_DATABASE_EXPORT IFileIOInfo : public WeakReferenceable
    {
        DEFINE_CAST_BASE(gcmp::IFileIOInfo)

        friend IIOStream & operator << (IIOStream & ioStream, const IFileIOInfo & fileIOInfo);

    public:
        /// \brief 析构函数
        ///
        /// \return 无
        virtual ~IFileIOInfo() = 0;

        /// \brief 获取所属模块组的Guid
        /// \return 返回所属的模块组Guid
        virtual Guid GetModuleGroupGuid() const = 0;

        /// \brief 设置文件保存名称，名称不要以数字开头，如不要 1_xxx
        /// \return void
        virtual void SetFileName(const std::wstring& fileName) = 0;

        /// \brief 获得文件的保存名称
        /// \return 返回文件的保存名称
        virtual const std::wstring& GetFileName() const = 0;

        /// \brief 获得该文件下的所有对象保存信息
        /// \param pObjectInfos 该文件下的所有对象保存信息
        /// \return 无
        virtual void GetObjectInfos(std::vector<const IObjectIOInfo*>& pObjectInfos) const = 0;

        /// \brief 向该文件保存信息中增加对象保存信息
        /// \param opObjectInfo 需增加的对象保存信息
        /// \return 无
        virtual void AddObjectInfo(OwnerPtr<IObjectIOInfo> opObjectInfo) = 0;
    };

    IIOStream & operator << (IIOStream & iostream, const IFileIOInfo & fileIOInfo);

    /// \brief 文件保存策略接口
    ///
    /// 实现自己的文件保存策略后需通过IFileIOStrategyManager注册该策略
    class GCMP_DATABASE_EXPORT IFileIOStrategy
    {
        DEFINE_CAST_BASE(gcmp::IFileIOStrategy)
    public:
        /// \brief 析构函数
        ///
        /// \return 无
        virtual ~IFileIOStrategy() = 0;

        /// \brief 根据ElementIds构建数据文件的存储结构
        /// \param pDocument 正在保存的文档
        /// \param elementIds 需要存储的ElementId
        /// \param opFileIOInfos 构建出的所有数据文件的文件保存信息
        /// \return 构建数据文件的存储结构成功返回true，不成功返回false
        virtual bool GetFileIOInfos(const IDocument * pDocument, const std::vector<ElementId> & elementIds, std::vector<OwnerPtr<IFileIOInfo>>& opFileIOInfos) = 0;

        /// \brief 获取该文件保存策略唯一标识字符串
        /// \return 该文件保存策略唯一标识字符串
        virtual std::wstring GetGuidAsWString() const = 0;

        /// \brief 查询是否开启了按模块组分区存储
        ///
        /// 默认不开启，开启后和GetFileIOInfosOfModuleGroupPartition()一起替代GetFileIOInfos()
        /// \return 是否开启了按模块组分区存储
        /// \see GetFileIOInfosOfModuleGroupPartition()
        virtual bool EnablePartitioningByModuleGroup() const = 0;

        /// \brief 给定模组和属于模组的对象Id，决定应该划分成数据文件来存储
        ///
        /// 如果没有开启按模块组分区存储，此函数不会被调用。
        /// \param moduleGroupId 模组
        /// \param elementIds 属于模组的对象
        /// \param opFileIOInfos 划分成的数据文件
        /// \return 是否操作成功
        /// \see EnablePartitioningByModuleGroup()
        virtual bool GetFileIOInfosOfModuleGroupPartition(
            const Guid & moduleGroupId,
            const std::vector<ElementId> & elementIds,
            std::vector<OwnerPtr<IFileIOInfo>> & opFileIOInfos
        ) = 0;
    };
}
